 ;
 ;                             Copyright (c) 1984-2020
 ;                              Benjamin David Lunt
 ;                             Forever Young Software
 ;                            fys [at] fysnet [dot] net
 ;                              All rights reserved
 ; 
 ; Redistribution and use in source or resulting in  compiled binary forms with or
 ; without modification, are permitted provided that the  following conditions are
 ; met.  Redistribution in printed form must first acquire written permission from
 ; copyright holder.
 ; 
 ; 1. Redistributions of source  code must retain the above copyright notice, this
 ;    list of conditions and the following disclaimer.
 ; 2. Redistributions in printed form must retain the above copyright notice, this
 ;    list of conditions and the following disclaimer.
 ; 3. Redistributions in  binary form must  reproduce the above copyright  notice,
 ;    this list of  conditions and the following  disclaimer in the  documentation
 ;    and/or other materials provided with the distribution.
 ; 
 ; THIS SOFTWARE, DOCUMENTATION, BINARY FILES, OR OTHER ITEM, HEREBY FURTHER KNOWN
 ; AS 'PRODUCT', IS  PROVIDED BY THE COPYRIGHT  HOLDER AND CONTRIBUTOR "AS IS" AND
 ; ANY EXPRESS OR IMPLIED  WARRANTIES, INCLUDING, BUT NOT  LIMITED TO, THE IMPLIED
 ; WARRANTIES  OF  MERCHANTABILITY  AND  FITNESS  FOR  A  PARTICULAR  PURPOSE  ARE 
 ; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  OWNER OR CONTRIBUTOR BE LIABLE FOR
 ; ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  OR CONSEQUENTIAL DAMAGES
 ; (INCLUDING, BUT NOT LIMITED TO,  PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES;
 ; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER  CAUSED AND ON
 ; ANY  THEORY OF  LIABILITY, WHETHER  IN  CONTRACT,  STRICT  LIABILITY,  OR  TORT 
 ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN  ANY WAY  OUT OF THE USE OF THIS
 ; PRODUCT, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  READER AND/OR USER
 ; USES AS THEIR OWN RISK.
 ; 
 ; Any inaccuracy in source code, code comments, documentation, or other expressed
 ; form within Product,  is unintentional and corresponding hardware specification
 ; takes precedence.
 ; 
 ; Let it be known that  the purpose of this Product is to be used as supplemental
 ; product for one or more of the following mentioned books.
 ; 
 ;   FYSOS: Operating System Design
 ;    Volume 1:  The System Core
 ;    Volume 2:  The Virtual File System
 ;    Volume 3:  Media Storage Devices
 ;    Volume 4:  Input and Output Devices
 ;    Volume 5:  ** Not yet published **
 ;    Volume 6:  The Graphical User Interface
 ;    Volume 7:  ** Not yet published **
 ;    Volume 8:  USB: The Universal Serial Bus
 ; 
 ; This Product is  included as a companion  to one or more of these  books and is
 ; not intended to be self-sufficient.  Each item within this distribution is part
 ; of a discussion within one or more of the books mentioned above.
 ; 
 ; For more information, please visit:
 ;             http://www.fysnet.net/osdesign_book_series.htm
 
 ;  Last updated: 19 July 2020

; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; strcpy(dest, src)
; copies a string from src to dest
; On entry:  (dest, src)
; On return: nothing
strcpy     proc near
           
           push ebp
           mov  ebp,esp
           
           push edi
           push esi
           
           mov  edi,PARAM0 ; dest
           mov  esi,PARAM1 ; src
           cld
@@:        lodsb
           stosb
           or   al,al
           jnz  short @b
           
           pop  esi
           pop  edi
           
           pop  ebp
           ret  8
strcpy     endp

; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; strncpyz()
; copies a string from src to dest, stops at len - 1, asciiz's it
; On entry:  (dest, src, len)
; On return: nothing
strncpyz   proc near
           
           push ebp
           mov  ebp,esp
           
           push edi
           push esi
           
           mov  edi,PARAM0 ; dest
           mov  esi,PARAM1 ; src
           mov  ecx,PARAM2 ; len
           .adsize
           jcxz short strncpyz_done
           
           cld
@@:        lodsb
           stosb
           or   al,al
           jz   short @f
           loop @b
           
@@:        mov  byte [edi-1],0
           
strncpyz_done:
           pop  esi
           pop  edi
           
           pop  ebp
           ret  12
strncpyz   endp

; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; memcpy()
; copies a buffer from src to dest of len in length
; On entry:  (dest, src, len)
; On return: nothing
memcpy     proc near
           
           push ebp
           mov  ebp,esp
           
           push edi
           push esi
           
           mov  edi,PARAM0  ; dest
           mov  esi,PARAM1  ; src
           mov  ecx,PARAM2  ; len
           cld
           rep
            movsb
           
           pop  esi
           pop  edi
           
           pop  ebp
           ret  12
memcpy     endp

; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; memset()
; sets a buffer's contents to a given value
; On entry:  (dest, val, len)
; On return: nothing
memset     proc near
           
           push ebp
           mov  ebp,esp
           
           push edi
           
           mov  edi,PARAM0  ; dest
           mov  eax,PARAM1  ; val
           mov  ecx,PARAM2  ; len
           cld
           rep
            stosb
           
           pop  edi
           
           pop  ebp
           ret  12
memset     endp

; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; outpb(addr, byte)
; sends the byte to addr
; On entry:  (addr, byte)
; On return: byte
outpb      proc near
           push ebp
           mov  ebp,esp           
           
           push eax
           push edx
           
           mov  edx,PARAM0
           mov  eax,PARAM1
           out  dx,al
           
           pop  edx
           pop  eax
           
           pop  ebp
           ret  8
outpb      endp

; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; iodelay()
; delays a short time for the IO to happen
; On entry:  nothing
; On return: nothing
iodelay    proc near
           push ebp
           mov  ebp,esp
           
           ; at this time we do nothing since we
           ;  assume a 486 will delay for us.
           
           ; however, older computers needed a small delay
           ; between I/O accesses.  If we will have a
           ; 486+, we can skip this function and remove
           ; it from the code.
           
           pop  ebp
           ret
iodelay    endp

; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; mul64_32()
; multiplies edx:eax by ecx
; On entry:  edx:eax = value to multiply
;            ecx     = multiplier
; On return: edx:eax = product
mul64_32   proc near
           push ebp
           mov  ebp,esp
           
           or   edx,edx         ; test for edx as zero.
           jnz  short long_way  ; if so, just 'mul ecx' and return
           
           mul  ecx
           pop  ebp
           ret

; long way
;      ebx  = edx * ecx (ignore the overflow into edx)
;  edx:eax  = (orginal) eax * ecx
;  edx:eax += ebx:zero
long_way:  push ebx
           
           mov  ebx,eax         ; save original eax in ebx
           mov  eax,edx         ; eax = edx
           mul  ecx             ;  = edx * ecx
           xchg ebx,eax         ; save result in ebx, restoring eax
           mul  ecx             ;  = eax * ecx
           add  edx,ebx         ;
           
           pop  ebx
           pop  ebp
           ret
mul64_32   endp

; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; min()
; returns the minimum value of eax and ecx
; On entry:  eax and ecx (signed values)
; On return: eax = the lesser of eax and ecx
min        proc near
           push ebp
           mov  ebp,esp
           
           cmp  eax,ecx
           jle  short @f
           xchg eax,ecx
           
@@:        pop  ebp
           ret
min        endp

; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; cmp64bitregs()
; compare two 64-bit values
; On entry:  ecx:ebx is compared to edx:eax
; On return: carry set if ecx:ebx < edx:eax
;            zero  set if both are equ
cmp64bitregs proc near
           cmp  ecx,edx
           jne  short @f
           cmp  ebx,eax
@@:        ret
cmp64bitregs endp


.end
